package gbase

import (
	"encoding/xml"
	"strings"

	"github.com/bytedance/sonic"
	"github.com/cloudwego/hertz/pkg/app/server/binding"
	jsoniter "github.com/json-iterator/go"
)

// 全局基类
type Base struct { /*这里不能写字段名*/
}

func (b *Base) ToString(child any) string {
	str, _ := jsoniter.MarshalToString(child)
	return str
}

func (b *Base) ToBytes(child any) []byte {
	bytes, _ := jsoniter.Marshal(child)
	return bytes
}

func (b *Base) ToMap(child any) (cm Map) {
	cm = Map{}
	_ = cm.FromX(child)
	return
}

func (b *Base) ToMapExclude(child any, keys ...string) (cm Map) {
	return b.ToMap(child).RemoveKeys(keys...)
}

func (b *Base) ToMapInclude(child any, keys ...string) (cm Map) {
	all := b.ToMap(child)
	cm = Map{}
	for _, v := range keys {
		if all.Exist(v) {
			cm[v] = all[v]
		}
	}
	return
}

func (b *Base) FromForm(child any, formStr string) (err error) {
	list := strings.Split(formStr, "&")
	m := make(map[any]any)
	if len(list) > 0 {
		for _, v := range list {
			cur := strings.Split(v, "=")
			if len(cur) == 2 {
				m[cur[0]] = cur[1]
			}
		}
	}
	if len(m) > 0 {
		bytes, err := jsoniter.Marshal(m)
		if err != nil {
			return err
		}
		return jsoniter.Unmarshal(bytes, child)
	}
	return nil
}

func (b *Base) FromString(child any, data string) error {
	if data != "" {
		return sonic.UnmarshalString(data, child)
	}
	return nil
}

func (b *Base) FromBytes(child any, data []byte) error {
	if len(data) > 0 {
		return sonic.Unmarshal(data, child)
	}
	return nil
}

// map or struct
func (b *Base) FromStruct(child any, data any) error {
	jsonBytes, err := sonic.Marshal(data)
	if err != nil {
		return err
	}
	return sonic.Unmarshal(jsonBytes, child)
}

// TODO: 优化替代
//func (b *Base) FromX(child any, params any) error {
// 	switch params := params.(type) {
// 	case []byte:
// 		return b.FromBytes(child, params)
// 	case string:
// 		return b.FromString(child, params)
// 	default:
// 		return b.FromStruct(child, params)
// 	}
// }

// from string,[]byte,map,struct
func (b *Base) FromX(child any, params any) error {
	var (
		jsonBytes []byte
		err       error
	)
	switch v := params.(type) {
	case []byte:
		jsonBytes = v
	case string:
		jsonBytes = StringToBytes(v) //unsafe.Slice(unsafe.StringData(v), len(v))
		// jsonBytes = []byte(v)
	default:
		jsonBytes, err = jsoniter.Marshal(params)
		if err != nil {
			return err
		}
	}
	if len(jsonBytes) > 0 {
		return jsoniter.Unmarshal(jsonBytes, child)
	}

	return nil
}

// func (b *Base) FromXold(child any, params any) error {
// 	var (
// 		jsonBytes []byte
// 		err       error
// 	)
// 	switch v := params.(type) {
// 	case []byte:
// 		jsonBytes = v
// 	case string:
// 		// jsonBytes = unsafe.Slice(unsafe.StringData(v), len(v))
// 		jsonBytes = []byte(v)
// 	default:
// 		jsonBytes, err = jsoniter.Marshal(params)
// 		if err != nil {
// 			return err
// 		}
// 	}
// 	if len(jsonBytes) > 0 {
// 		return jsoniter.Unmarshal(jsonBytes, child)
// 	}

// 	return nil
// }

func (b *Base) FromXBySonic(child any, params any) error {
	var (
		jsonBytes []byte
		err       error
	)
	switch v := params.(type) {
	case []byte:
		jsonBytes = v
	case string:
		jsonBytes = StringToBytes(v) //unsafe.Slice(unsafe.StringData(v), len(v))
		// jsonBytes = []byte(v)
	default:
		jsonBytes, err = sonic.Marshal(params)
		if err != nil {
			return err
		}
	}
	if len(jsonBytes) > 0 {
		return sonic.Unmarshal(jsonBytes, child)
	}
	return nil
}

func (b *Base) FromXml(child any, xmlStr string) error {
	return xml.Unmarshal([]byte(xmlStr), child)
}

func (b *Base) Vd(child any) error {
	return binding.Validate(child)
}
